package com.nebula.poi.config;

import com.nebula.poi.annotation.ExcelAnnotation;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author: llq
 * @Date: 2019/11/27
 */
public class ExcelImport<T> {
    Class<T> clazz;

    public ExcelImport(Class<T> clazz) {
        this.clazz = clazz;
    }

    public Map<String, Object> importExcel(File file, String... pattern) {
        Collection<T> dist = new ArrayList();
        Map<String, Object> resultMap = new HashMap<String, Object>();
        try {
            /**
             * 类反射得到调用方法
             */
            // 得到目标目标类的所有的字段列表
            Field filed[] = clazz.getDeclaredFields();
            // 将所有标有Annotation的字段，也就是允许导入数据的字段,放入到一个map中
            Map fieldmap = new HashMap();
            Map<String, String> mapExport = new HashMap<String, String>();
            // 循环读取所有字段
            for (int i = 0; i < filed.length; i++) {
                Field f = filed[i];
                // 得到单个字段上的Annotation
                ExcelAnnotation exa = f.getAnnotation(ExcelAnnotation.class);
                // 如果标识了Annotationd的话
                if (exa != null) {
                    // 构造设置了Annotation的字段的Setter方法
                    String fieldname = f.getName();
                    String setMethodName = "set" + fieldname.substring(0, 1).toUpperCase() + fieldname.substring(1);
                    // 构造调用的method，
                    Method setMethod = clazz.getMethod(setMethodName, new Class[] { f.getType() });
                    // 将这个method以Annotaion的名字为key来存入。
                    System.err.println("exa.exportName()=" + exa.exportName() + ",setMethod=" + setMethodName);
                    fieldmap.put(exa.exportName(), setMethod);
                    mapExport.put(fieldname, exa.exportName());
                }
            }
            /**
             * excel的解析开始
             */
            // 将传入的File构造为FileInputStream;
            FileInputStream in = new FileInputStream(file);
            // 得到工作表
            HSSFWorkbook book = new HSSFWorkbook(in);
            // 得到第一页
            HSSFSheet sheet = book.getSheetAt(0);
            // 得到第一面的所有行
            Iterator<Row> row = sheet.rowIterator();

            /**
             * 标题解析
             */
            // 得到第一行，也就是标题行
            Row title = row.next();
            // 得到第一行的所有列
            Iterator<Cell> cellTitle = title.cellIterator();
            // 将标题的文字内容放入到一个map中。
            Map titlemap = new HashMap();
            // 从标题第一列开始
            int i = 0;
            // 循环标题所有的列
            while (cellTitle.hasNext()) {
                Cell cell = cellTitle.next();
                String value = "";
                if (cell.getCellType() == 0) {
                    value = cell.getNumericCellValue() + "";
                } else {
                    value = cell.getStringCellValue();
                }
                titlemap.put(i, value);
                System.err.println(value);
                i = i + 1;
            }
            // titlemap {0=姓名, 1=性别, 2=身份证号, 3=出生日期, 4=出生地, 5=民族, 6=国籍/地区,
            // 7=家庭地址, 8=现住址, 9=户口所在地}
            // mapExport {presentAddress=现住址, birthAddress=出生地, birthdate=出生日期,
            // idcard=身份证号, gender=性别, realName=姓名, accountAddress=户口所在地,
            // nation=民族, familyAddress=家庭地址, country=国籍/地区}
            String fieldStr = "";
            List<Map<String, String>> headList = new ArrayList<Map<String, String>>();
            List<String> fieldList = new ArrayList<String>();
            for (Map.Entry<String, String> entry : mapExport.entrySet()) {
                if (titlemap.containsValue(entry.getValue())) {
                    Map<String, String> headMap = new HashMap<String, String>(1);
                    headMap.put(entry.getKey(), entry.getValue());
                    headList.add(headMap);

                } else {
                    fieldList.add(entry.getKey());
                    fieldStr += "," + entry.getKey();

                }
            }
            if (fieldStr.equals("")) {
                resultMap.put("fieldStr", null);
            } else {
                fieldStr = fieldStr.substring(1);
                resultMap.put("fieldStr", fieldStr);
            }
            resultMap.put("fieldList", fieldList);
            resultMap.put("headList", headList);

            /**
             * 解析内容行
             */
            // 用来格式化日期的DateFormat
            SimpleDateFormat sf;
            if (pattern.length < 1) {
                sf = new SimpleDateFormat("yyyy-MM-dd");
            } else
                sf = new SimpleDateFormat(pattern[0]);
            Map<String, List<String>> randomMap = new HashMap<String, List<String>>();
            List<String> randomList = new ArrayList<String>();
            while (row.hasNext()) {
                // 标题下的第一行
                Row rown = row.next();
                int rowNum = rown.getRowNum();
                // 行的所有列
                Iterator<Cell> cellbody = rown.cellIterator();
                // 得到传入类的实例
                T tObject = clazz.newInstance();
                int k = 0;
                // int headIndex = headList.size();
                int headIndex = titlemap.size();
                // 遍历一行的列
                while (k < headIndex) {
                    Cell cell = rown.getCell(k);
                    // 这里得到此列的对应的标题
                    String titleString = (String) titlemap.get(k);
                    // 如果这一列的标题和类中的某一列的Annotation相同，那么则调用此类的的set方法，进行设值
                    if (fieldmap.containsKey(titleString)) {
                        Method setMethod = (Method) fieldmap.get(titleString);
                        // 得到setter方法的参数
                        Class<?>[] ts = setMethod.getParameterTypes();
                        // 只要一个参数
                        Object xclass = ts[0];
                        // 判断参数类型
                        String value = "";
                        if (cell == null || cell.equals("")) {
                            value = "";
                        } else if (cell.getCellType() == 0) {
                            if (HSSFDateUtil.isCellDateFormatted(cell)) {
                                Date date = cell.getDateCellValue();
                                DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
                                value = dateFormat.format(date);
                            } else {
                                Double d1 = ((Double) cell.getNumericCellValue());
                                Long l1 = ((Double) cell.getNumericCellValue()).longValue();
                                if (d1 == l1.doubleValue()) {// 是整数
                                    value = ((Double) cell.getNumericCellValue()).longValue() + "";
                                } else {// 不是整数
                                    value = ((Double) cell.getNumericCellValue()) + "";
                                }
                            }
                        } else {
                            value = cell.getStringCellValue();
                        }

                        if (xclass instanceof java.lang.String) {
                            setMethod.invoke(tObject, value);
                        } else if (xclass instanceof Date) {
                            setMethod.invoke(tObject, sf.parse(cell.getStringCellValue()));
                        } else if (xclass instanceof Boolean) {
                            String boolname = "是";
                            if (cell.getStringCellValue().equals("否")) {
                                boolname = "否";
                            }
                            setMethod.invoke(tObject, boolname);
                        } else if (xclass == Double.class && cell != null) {
                            if (cell.getCellType() == 0) {
                                setMethod.invoke(tObject, (Double) cell.getNumericCellValue());
                            } else {
                                if (cell.getStringCellValue().equals("") || cell.getStringCellValue() == null) {
                                    // setMethod.invoke(tObject, -1.0);
                                    System.out.println("1");
                                } else {
                                    setMethod.invoke(tObject, Double.parseDouble(cell.getStringCellValue()));
                                }
                            }

                        } else if (xclass == Integer.class) {
                            Integer ii = (value == null || value.equals("")) ? 0 : Integer.parseInt(value);
                            setMethod.invoke(tObject, ii);
                        } else {
                            value = value.equals("") ? null : value;
                            setMethod.invoke(tObject, value);
                        }
                    } else {
                        String value = "";
                        if (cell == null || cell.equals("")) {
                            value = "";
                        } else if (cell.getCellType() == 0) {
                            if (HSSFDateUtil.isCellDateFormatted(cell)) {
                                Date date = cell.getDateCellValue();
                                DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
                                value = dateFormat.format(date);
                            } else {
                                value = ((Double) cell.getNumericCellValue()) + "";
                            }
                        } else {
                            if (cell.getStringCellValue() == null || cell.getStringCellValue().equals("")) {
                                // value = "0.0";
                            } else {
                                value = cell.getStringCellValue();
                            }
                        }
                        randomList = randomMap.get(titleString);
                        if (randomList != null) {
                            randomList.add(value);
                            randomMap.put(titleString, randomList);
                        } else {
                            List<String> random_new = new ArrayList<String>();
                            random_new.add(value);
                            randomMap.put(titleString, random_new);
                        }
                    }
                    // 下一列
                    k = k + 1;
                }
                // if (tObject instanceof TeacherExcel) {
                // ((TeacherExcel) tObject).setRowNum(rowNum + 1);
                // }
                dist.add(tObject);
            }
            resultMap.put("data", dist);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return resultMap;
    }
}
